<template>
    <div class="xpage">
        <div class="left_obj">
            <div v-for="item in deviceTypeList" :key="item.label" draggable="true"
                @dragstart="handleDragStart($event, item)" class="draggable-item">
                <img style="width:50px;height:50px" :src="type_icon_map[item.type]" alt="">
                <div>
                    {{ item.label }}
                </div>
            </div>
            <div class="draggable-item" @click="export_svg()">
                toJSON() 导出
            </div>
        </div>
        <svg ref="container" id="container" class="my_container" 
             @dragover="handleDragOver" 
             @drop="handleDrop" 
             @mousemove="handleMouseMove" 
             @click="handleCanvasClick"
             @contextmenu.prevent="handleCanvasRightClick"></svg>
        <a-modal v-model:visible="modalVisible" :title="`编辑设备`" @ok="handleModalOk" @cancel="handleModalCancel">
            <div class="update_item">
                <span> 请输入设备名称: </span>
                <a-input style="width:160px" @change="change_device" v-model:value="deviceForm.deviceName"
                    class="val_item">
                </a-input>
            </div>
            <div class="update_item">
                <span style="color:#fff">请选择需要绑定的设备: </span>
                <a-select style="width:160px" :field-names="{ label: 'label', value: 'deviceNo' }" class="val_item"
                    v-model:value="deviceForm.deviceNo" :options="device_list" placeholder="请选择设备">
                </a-select>
            </div>
            <div class="update_item">
                <span style="color:#fff">请选择需要绑定的点位: </span>
                <a-select style="width:160px" :field-names="{ label: 'label', value: 'tagcode' }"
                    @change="change_tagcode" class="val_item" mode="multiple" placeholder="请选择参数"
                    :options="tagcode_ptions" />
            </div>
        </a-modal>
    </div>
</template>

<script setup>
import { onMounted, ref, reactive, onBeforeUnmount } from 'vue';
import { SVG } from '@svgdotjs/svg.js';
import '@svgdotjs/svg.draggable.js';

// 默认图片URL
const DEFAULT_IMAGE = 'https://gw.alipayobjects.com/zos/bmw-prod/c55d7ae1-8d20-4585-bd8f-ca23653a4489.svg';

const container = ref(null);

// 图标导入
import pcsIcon from '@/assets/svg_icon/icon01.svg';
import bmsIcon from '@/assets/svg_icon/icon02.svg';
import meterIcon from '@/assets/svg_icon/icon03.svg';

let pcsIcon_64 = pcsIcon;
let bmsIcon_64 = bmsIcon;
let meterIcon_64 = meterIcon;

let modalVisible = ref(false);
let selectedDevice = ref(null);

// 连接状态管理
const connectingState = reactive({
    isConnecting: false,
    sourceNode: null,
    tempLine: null,
    lastMouseX: 0,
    lastMouseY: 0,
    currentTarget: null, // 当前目标节点
});

// 设备图标映射
const type_icon_map = {
    27: pcsIcon_64,
    28: bmsIcon_64,
    1: meterIcon_64,
};

// 设备列表
const deviceTypeList = [
    { label: 'PCS', type: '27' },
    { label: 'BMS', type: '28' },
    { label: '电表1', type: '1' }
];

// 设备参数配置
const deviceParamsConfig = {
    1: [
        { key: 'power', label: '功率', unit: 'kW', defaultValue: '10' },
        { key: 'voltage', label: '电压', unit: 'V', defaultValue: '220' }
    ],
    27: [
        { key: 'capacity', label: '容量', unit: 'kWh', defaultValue: '50' },
        { key: 'efficiency', label: '效率', unit: '%', defaultValue: '95' }
    ],
    28: [
        { key: 'cells', label: '电池数量', unit: '节', defaultValue: '16' },
        { key: 'temperature', label: '温度', unit: '°C', defaultValue: '25' }
    ]
};

const svg = ref(null);
const draggedItem = ref(null);
const deviceForm = reactive({
    deviceName: '',
    deviceNo: '',
    tagcode: []
});
const nodes = ref([]);
const edges = ref([]);

// 创建连线层
let connectorLayer = null;

// 更新所有连线位置
const updateEdges = () => {
    edges.value.forEach(edge => {
        const source = edge.source;
        const target = edge.target;
        const sourceX = source.x() + source.width() / 2;
        const sourceY = source.y() + source.height() / 2;
        const targetX = target.x() + target.width() / 2;
        const targetY = target.y() + target.height() / 2;
        edge.line.plot(sourceX, sourceY, targetX, targetY);
    });
};

// 添加新连线
const addEdge = (source, target) => {
    const sourceX = source.x() + source.width() / 2;
    const sourceY = source.y() + source.height() / 2;
    const targetX = target.x() + target.width() / 2;
    const targetY = target.y() + target.height() / 2;
    
    // 使用贝塞尔曲线
    const dx = targetX - sourceX;
    const dy = targetY - sourceY;
    const controlOffset = Math.sqrt(dx * dx + dy * dy) * 0.3;
    
    const controlPoint1X = sourceX + dx * 0.5 - dy * 0.3;
    const controlPoint1Y = sourceY + dy * 0.5 + dx * 0.3;
    const controlPoint2X = sourceX + dx * 0.5 + dy * 0.3;
    const controlPoint2Y = sourceY + dy * 0.5 - dx * 0.3;
    
    // 确保连线层存在
    if (!connectorLayer) {
        connectorLayer = svg.value.group().back();
    }
    
    // 将连线添加到连线层
    const line = connectorLayer.path(`M ${sourceX} ${sourceY} C ${controlPoint1X} ${controlPoint1Y}, ${controlPoint2X} ${controlPoint2Y}, ${targetX} ${targetY}`)
        .stroke({ 
            width: 2, 
            color: '#3498db',
            linecap: 'round'
        })
        .fill('none');

    // 添加箭头标记
    line.marker('end', svg.value.marker(10, 10, function(add) {
        add.path('M0,0 L10,5 L0,10 Z').fill('#3498db');
    }).attr('orient', 'auto'));

    const edge = { source, target, line };
    edges.value.push(edge);

    // 添加点击事件以删除连线
    line.click(() => {
        line.remove();
        const index = edges.value.indexOf(edge);
        if (index !== -1) {
            edges.value.splice(index, 1);
        }
    });

    return edge;
};

// 模态框确定
const handleModalOk = () => {
    const selectedNode = nodes.value.find(node => node.data('deviceName') === deviceForm.deviceName);
    if (selectedNode) {
        selectedNode.data('deviceName', deviceForm.deviceName);
        selectedNode.data('deviceNo', deviceForm.deviceNo);
        selectedNode.data('tagcode', deviceForm.tagcode);
    }
    modalVisible.value = false;
};

// 模态框取消
const handleModalCancel = () => {
    modalVisible.value = false;
};

// 设备名称变化
const change_device = (event) => {
    deviceForm.deviceName = event.target.value;
};

// 标签变化
const change_tagcode = (value) => {
    deviceForm.tagcode = value;
};

// 导出SVG
const export_svg = () => {
    const svgData = svg.value.svg();
    console.log(svgData);
};

// 创建设备节点
const createDeviceNode = (item, position) => {
    let params = {};
    const paramsConfig = deviceParamsConfig[item.type] || [];
    paramsConfig.forEach(param => {
        params[param.key] = param.defaultValue;
    });

    const node = svg.value.group();
    const rect = node.rect(120, 100).radius(6).fill('#EFF4FF').stroke({ 
        color: '#5F95FF', 
        width: 1 
    });
    
    const image = node.image(type_icon_map[item.type], 40, 40).cx(40).cy(10);
    const text = node.text(item.label).font({ 
        size: 13, 
        fill: '#262626' 
    }).cx(60).cy(65);
    
    const paramText = node.text(paramsConfig.map(p => `${p.label}: ${params[p.key]}${p.unit}`).join('\n'))
        .font({ size: 12, fill: '#666' }).cx(60).cy(80);

    node.move(position.x, position.y);
    node.data('type', item.type);
    node.data('label', item.label);
    node.data('params', params);
    node.data('deviceNo', '');
    node.data('data_res', []);
    
    // 悬停效果
    node.mouseover(() => {
        if (!connectingState.isConnecting || connectingState.sourceNode !== node) {
            rect.stroke({ color: '#1890ff', width: 2 });
        }
        
        // 连线模式下的目标节点高亮
        if (connectingState.isConnecting && connectingState.sourceNode !== node) {
            rect.stroke({ color: '#7CB305', width: 3 });
            connectingState.currentTarget = node;
        }
    });
    
    node.mouseout(() => {
        if (!connectingState.isConnecting || connectingState.sourceNode !== node) {
            rect.stroke({ color: '#5F95FF', width: 1 });
        }
        
        // 连线模式下离开目标节点
        if (connectingState.isConnecting && connectingState.currentTarget === node) {
            rect.stroke({ color: '#5F95FF', width: 1 });
            connectingState.currentTarget = null;
        }
    });
    
    // 右键点击事件 - 用于开始/完成连接
    node.on('contextmenu', (e) => {
        e.preventDefault();
        
        if (!connectingState.isConnecting) {
            // 开始新连接
            startConnection(node);
        } else {
            // 完成连接
            if (connectingState.sourceNode !== node) {
                addEdge(connectingState.sourceNode, node);
                cancelConnection();
            }
        }
    });
    
    // 左键点击事件 - 打开编辑模态框
    node.click(() => {
        deviceForm.deviceName = node.data('label');
        deviceForm.deviceNo = node.data('deviceNo') || '';
        deviceForm.tagcode = node.data('tagcode') || [];
        modalVisible.value = true;
    });
    
    // 双击事件 - 删除节点
    node.dblclick(() => {
        // 删除节点
        node.remove();
        
        // 删除相关连线
        edges.value = edges.value.filter(edge => {
            if (edge.source === node || edge.target === node) {
                edge.line.remove();
                return false;
            }
            return true;
        });
        
        // 从节点列表中移除
        nodes.value = nodes.value.filter(n => n !== node);
    });

    // 使节点可拖动
    node.draggable();
    node.on('dragmove', () => {
        updateEdges();
    });

    return node;
};

// 开始连接
const startConnection = (node) => {
    console.log('开始连线，源节点:', node);
    connectingState.isConnecting = true;
    connectingState.sourceNode = node;
    
    // 高亮源节点
    const rect = node.findOne('rect');
    rect.stroke({ color: '#FF4D4F', width: 3 });
    
    // 创建临时连接线
    const sourceX = node.x() + node.width() / 2;
    const sourceY = node.y() + node.height() / 2;
    
    // 确保连线层存在
    if (!connectorLayer) {
        connectorLayer = svg.value.group().back();
    }
    
    // 将临时连接线添加到连线层
    connectingState.tempLine = connectorLayer.path(`M ${sourceX} ${sourceY} L ${sourceX} ${sourceY}`)
        .stroke({ 
            width: 2, 
            color: '#FF4D4F', 
            dasharray: '5,5',
            linecap: 'round'
        })
        .fill('none');
};

// 取消连接
const cancelConnection = () => {
    if (connectingState.tempLine) {
        connectingState.tempLine.remove();
    }
    
    // 恢复源节点样式
    if (connectingState.sourceNode) {
        const rect = connectingState.sourceNode.findOne('rect');
        rect.stroke({ color: '#5F95FF', width: 1 });
    }
    
    // 恢复当前目标节点样式
    if (connectingState.currentTarget) {
        const rect = connectingState.currentTarget.findOne('rect');
        rect.stroke({ color: '#5F95FF', width: 1 });
        connectingState.currentTarget = null;
    }
    
    connectingState.isConnecting = false;
    connectingState.sourceNode = null;
    connectingState.tempLine = null;
};

// 处理鼠标移动
const handleMouseMove = (e) => {
    // 更新连接线的终点位置
    if (connectingState.isConnecting && connectingState.tempLine) {
        // 获取SVG容器的边界框
        const rect = container.value.getBoundingClientRect();
        
        // 计算鼠标在SVG坐标系中的位置
        const x = e.clientX - rect.left;
        const y = e.clientY - rect.top;
        
        console.log("鼠标位置:", x, y);
        
        const sourceX = connectingState.sourceNode.x() + connectingState.sourceNode.width() / 2;
        const sourceY = connectingState.sourceNode.y() + connectingState.sourceNode.height() / 2;
        
        // 使用贝塞尔曲线使连线更平滑
        const dx = x - sourceX;
        const dy = y - sourceY;
        const controlOffset = Math.sqrt(dx * dx + dy * dy) * 0.3;
        
        const controlPoint1X = sourceX + dx * 0.5 - dy * 0.3;
        const controlPoint1Y = sourceY + dy * 0.5 + dx * 0.3;
        const controlPoint2X = sourceX + dx * 0.5 + dy * 0.3;
        const controlPoint2Y = sourceY + dy * 0.5 - dx * 0.3;
        
        // 更新临时连接线
        connectingState.tempLine.plot(`M ${sourceX} ${sourceY} C ${controlPoint1X} ${controlPoint1Y}, ${controlPoint2X} ${controlPoint2Y}, ${x} ${y}`);
        
        // 记录鼠标位置
        connectingState.lastMouseX = x;
        connectingState.lastMouseY = y;
    }
};

// 处理画布点击
const handleCanvasClick = (e) => {
    // 点击空白处取消连接
    if (connectingState.isConnecting) {
        cancelConnection();
    }
};

// 处理画布右键
const handleCanvasRightClick = (e) => {
    // 在空白处右键取消连接
    if (connectingState.isConnecting) {
        cancelConnection();
    }
};

// 处理拖拽开始
const handleDragStart = (e, item) => {
    draggedItem.value = item;
    e.dataTransfer.setData('text/plain', item.label);
    e.dataTransfer.effectAllowed = 'copy';
};

// 处理拖拽经过
const handleDragOver = (e) => {
    e.preventDefault();
};

// 处理拖拽结束
const handleDrop = (e) => {
    e.preventDefault();
    
    // 获取放置位置
    const rect = container.value.getBoundingClientRect();
    const x = e.clientX - rect.left;
    const y = e.clientY - rect.top;
    
    if (draggedItem.value) {
        // 创建设备节点
        const node = createDeviceNode(draggedItem.value, { x, y });
        nodes.value.push(node);
        draggedItem.value = null;
    }
};

// 初始化SVG
onMounted(() => {
    svg.value = SVG(container.value).size('100%', '100%');
    
    // 创建连线层并放在最底层
    connectorLayer = svg.value.group().back();
    
    // 添加箭头标记定义
    svg.value.defs().marker(10, 10, function(add) {
        add.path('M0,0 L10,5 L0,10 Z').fill('#3498db');
    }).attr('id', 'arrowhead').attr('orient', 'auto');
});

// 组件销毁时清理
onBeforeUnmount(() => {
    cancelConnection();
});

</script>

<style scoped>
.xpage {
    display: flex;
    height: 100vh;
    background: #f5f5f5;
}

.left_obj {
    width: 200px;
    padding: 15px;
    border-right: 1px solid #ddd;
    background: #fff;
    box-shadow: 0 2px 8px rgba(0,0,0,0.1);
    z-index: 10;
}

.draggable-item {
    cursor: move;
    margin-bottom: 15px;
    padding: 10px;
    border-radius: 6px;
    background: #f0f7ff;
    border: 1px solid #d9e7ff;
    transition: all 0.2s;
    text-align: center;
}

.draggable-item:hover {
    background: #e6f4ff;
    border-color: #91caff;
    transform: translateY(-2px);
    box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}

.draggable-item img {
    display: block;
    margin: 0 auto 8px;
}

.my_container {
    flex: 1;
    background: #fafafa;
    border: 1px solid #eee;
}

.update_item {
    margin-bottom: 15px;
    display: flex;
    align-items: center;
}

.update_item span {
    width: 180px;
    display: inline-block;
}

.val_item {
    flex: 1;
}
</style>
